package com.avengers.core.kit;

import com.avengers.modules.epp.bean.emums.EppType;
import com.avengers.modules.spider.bean.enums.DomainWhoisType;
import com.avengers.modules.spider.whois.bean.WhoisInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.avengers.core.bean.enums.SymbolEnum.dot;
import static com.avengers.core.bean.enums.SymbolEnum.empty;

/**
 * @author yu.wang
 * @since 5/5/22 10:23 AM
 **/
public class DomainKit {
    private static final Logger logger = LoggerFactory.getLogger(DomainKit.class);
    private static final String PUNY_CODE_PREFIX = "xn--";

    public static EppType getEppType(String domain) {
        return EppType.of(domain);
    }

    public static boolean isIdn(String domain) {
        return RegexKit.hasChinese(domain);
    }

    public static String inspect(String domain) {
        if (null == domain) {
            return "";
        }
        domain = domain.trim().replaceAll("\\p{C}", "");
        if (isDomain(domain)) {
            return domain;
        }
        return "";
    }

    public static DomainWhoisType getWhoisType(String domain) {
        return DomainWhoisType.of(domain);
    }

    public static boolean isDomain(String domain) {
        boolean isDomain = RegexKit.match(RegexKit.DOMAIN_NAME, domain);
        if (isDomain) {
            return true;
        }
        if (!domain.contains(dot.string)) {
            return false;
        }
        String fromPunyCodeDomain = null;
        try {
            fromPunyCodeDomain = fromPunyCode(domain);
        } catch (Exception e) {
            logger.error("domain_{} match from punyCode error: {}", domain, e.getMessage(), e);
            return false;
        }
        return RegexKit.match(RegexKit.DOMAIN_NAME, fromPunyCodeDomain);
    }

    public static String getPrefix(String domain) {
        if (StringKit.isBlank(domain)) {
            return null;
        }
        int index = domain.indexOf(dot.string);
        if (index > 0) {
            return domain.substring(0, index).toLowerCase();
        }
        return null;
    }

    public static String getSuffix(String domain) {
        if (StringKit.isBlank(domain)) {
            return null;
        }
        int index = domain.indexOf(dot.string);
        if (index > 0) {
            return domain.substring(index).toLowerCase();
        }
        return null;
    }

    public static String filterDomain(String name) {
        String domain;
        try {
            domain = DomainKit.fromPunyCode(name);
            if (domain.equals(name)) {
                return domain;
            }
        } catch (Exception e) {
            logger.error("filter domain_{} error: {}", name, e.getMessage(), e);
            domain = name;
        }
        return RegexKit.match(RegexKit.DOMAIN_NAME, domain) ? domain : null;
    }

    public static String toPunyCode(String domain) {
        try {
            if (!domain.contains(dot.string)) {
                if (StringKit.hasChinese(domain)) {
                    return PUNY_CODE_PREFIX + PunyCode.encode(domain);
                }
                return domain;
            }
            String suffix = domain.substring(domain.indexOf(dot.string));
            String prefix = domain.substring(0, domain.indexOf(dot.string));
            prefix = StringKit.hasChinese(prefix) ? PUNY_CODE_PREFIX + PunyCode.encode(prefix) : prefix;
            suffix = StringKit.hasChinese(suffix) ? dot.string + PUNY_CODE_PREFIX + PunyCode.encode(suffix.substring(1)) : suffix;
            return prefix + suffix;
        } catch (Exception e) {
            logger.error("domain_{} transfer to punyCode error: {}", domain, e.getMessage(), e);
        }
        return domain;
    }

    public static String fromPunyCode(String punyCode) {
        try {
            if (!punyCode.contains(dot.string)) {
                return PunyCode.decode(punyCode.replace(PUNY_CODE_PREFIX, empty.string));
            }
            String suffix = punyCode.substring(punyCode.indexOf(dot.string));
            String prefix = punyCode.substring(0, punyCode.indexOf(dot.string));
            prefix = prefix.startsWith(PUNY_CODE_PREFIX) ? PunyCode.decode(prefix.toLowerCase().replace(PUNY_CODE_PREFIX, empty.string)) : prefix;
            suffix = suffix.startsWith(dot.string + PUNY_CODE_PREFIX) ? dot.string + PunyCode.decode(suffix.toLowerCase().replace(dot.string + PUNY_CODE_PREFIX, empty.string)) : suffix;
            return prefix + suffix;
        } catch (Exception e) {
            logger.error("domain_{} transfer from PunyCode error: {}", punyCode, e.getMessage(), e);
        }
        return punyCode;
    }

    public static WhoisInfo whoisInfo(String domain) {
        return WhoisKit.whoisInfo(domain);
    }

    public static String whoisSource(String domain) {
        return WhoisKit.source(domain);
    }
}
